#! /usr/bin/python
# -*- coding: utf-8 -*-

# Конвертор словаря Бориса Кондратьева из текстового формата в формат Mobipocket.
import os
import re
from u2palm import *

# Определение каталогов:
# Все конфигурационные файлы
DIR_CONFIG 		= "./config/"
# Каталог, где находятся исходные текстовые файлы словаря
DIR_SOURCE 		= "./eo-ru/"
# Каталог для словаря в формате DICT
DIR_DICT 		= "./dict/"
# В этот каталог нужно поместить управляющий файл для создания словаря: ervo.opf
# Здесь также можно разместить все дополнительные текстовые файлы для словаря
# в формате HTML (Mobipocket) и кодировке Unicode
DIR_MOBI 		= "./mobi/"
# В этот каталог будет скопировано содержимое каталого MOBI
# Все файлы при копировании будут сконвертированны для платформы PALM
DIR_PALM 		= "./palm/"
# Коталог где будут сохранены сгенирированные файлы XHTML в формате Unicode
DIR_MOBI_XHTML	= "./mobi/xhtml/"
# Коталог где будут сохранены сгенирированные файлы XHTML в формате Palm
DIR_PALM_XHTML  = "./palm/xhtml/"

cx2eo = {u'cx':u'ĉ', u'Cx':u'Ĉ', u'gx':u'ĝ', u'Gx':u'Ĝ', u'hx':u'ĥ', u'Hx':u'Ĥ',
         u'jx':u'ĵ', u'Jx':u'Ĵ', u'sx':u'ŝ', u'Sx':u'Ŝ', u'ux':u'ŭ', u'Ux':u'Ŭ',
         u'--':u'―', u',,':u';'}
         
gramatiko = {'a':'adjektivo', 'o':'substantivo', 'i':'verbo'}

# Константа определяющая русские буквы.
# Необходима для формирования обратного индекса по русским словам
RusaLetero = u"абвгдеёжзийклмнопрстуфхцчшщьыъэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЯ"

# Переменная для словаря DICT
out_dict = [u"""

00-database-info
        Предлагаемый вашему вниманию эсперанто-русский словарь является результатом пятнадцатилетней работы и предназначен для желающих овладеть международным языком эсперанто в достаточно полном объёме.
00-database-short
        Большой эсперанто-русский словарь Б.Кондратьева
00-database-url
        http://code.google.com/p/ervo/
00-database-utf8

"""]

# Глобальная переменная содержащая значение предыдущих ключей
# Необходима для устранения проблемы с дублирующимися ключами (Issue 2)
antaua_indekso = []

# Глобальная переменная для создания альтернативного индекса по первым трём буквам слова
threeSymbolsDict = {}

def deklinacii(vorto):
	"""
	Склонение по падежам и создание индекса по различным формам входного слова.
	На входе словарная форма слова: существительное в именительном падеж
	или глагол в неопределённой форме.
	
	Функция возвращает специальный код включающий все возможные формы слова
	для добавления в массив contents.
	"""
	
	radiko 	= vorto[:-1] # Получаем корень слова отбрасывая конечную букву
	finajxo = vorto[-1]  # Окончание слова
	
	if finajxo == 'i':	# Склонение глагола
		return u"""<idx:infl inflgrp="verbo">
<idx:iform name="preterito" value="%sis"/>
<idx:iform name="prezenco" value="%sas"/>
<idx:iform name="futuro" value="%sos"/>
<idx:iform name="imperativo" value="%su"/>
<idx:iform name="volitivo" value="%sus"/>
</idx:infl>""" % (radiko, radiko, radiko, radiko, radiko)

	elif finajxo == 'o':	# Склонение существительного
		return """<idx:infl inflgrp="substantivo">
<idx:iform name="elizio" value="%s"/>
<idx:iform name="pluralo" value="%soj"/>
<idx:iform name="akuzativo" value="%son"/>
<idx:iform name="pluralakuzativo" value="%sojn"/>
</idx:infl>""" % (radiko, radiko, radiko, radiko)

	elif finajxo == 'a':	# Склонение прилагательного
		return """<idx:infl inflgrp="adjektivo">
<idx:iform name="pluralo" value="%sj"/>
<idx:iform name="akuzativo" value="%sn"/>
<idx:iform name="pluralakuzativo" value="%sjn"/>
</idx:infl>""" % ( vorto, vorto, vorto )

	elif finajxo == 'j':
		return """<idx:infl inflgrp="pluralo">
<idx:iform name="akuzativo" value="%sn"/>
</idx:infl>""" % radiko

	# Если входное слово имеет окончание отличное от {o,i,a,j} то не склоняем
	return ''

def kreiIndekso(vorto, radiko):
	"""
	Создание индексов для Mobipocket.
	На входе получаем строчку полученную из квадратных кавычек "[...]"

	Возвращаем специально сформированный код xHTML.
	"""

	global antaua_indekso
	global threeSymbolsDict
	sxlosilo = ''
	vortoj = vorto.split(', ')
	out = []
	
	for x in vortoj:
		sxlosilo = x.replace(u' III','').replace(u' II', '').replace(u' I', u'')
		if len(sxlosilo) < 2: return ''

		sxlosilo = sxlosilo.replace('~', radiko).replace('/','').replace('|','')
		sxlosilo = sxlosilo.replace('(', '').replace(')', '').strip()

		# Если слово имеет несколько значений и было уже проиндексировано, то выходим
		if sxlosilo in antaua_indekso: return ''
			
		# Иначе добавляем новый ключ к списку использованных ключей
		antaua_indekso.append(sxlosilo)

		# Создаём отдельный индекс для аффиксов
		if (sxlosilo[0] == '-' or sxlosilo[-1] == '-') and len(sxlosilo) > 2:
			out.append(u'<idx:key name="Afikso" key="%s"/>' % sxlosilo)

		out.append('\n<A NAME="%s"></A><idx:orth "value = "%s">\n' % (sxlosilo, sxlosilo))

		# Составляем альтернативный индекс по первым трём буквам
		#firstThree = sxlosilo[0:3].lower()

		#if not firstThree in threeSymbolsDict:
		#	threeSymbolsDict[firstThree] = sxlosilo
                        
		# Добавляем в индексы варианты склонения слова
		if len(sxlosilo) > 1 and sxlosilo.find('-') < 0:
			out.append(deklinacii(sxlosilo))
			out_dict.append(u"\n")
			out_dict.append(unicode(sxlosilo))
			out_dict.append(u"\n")
		out.append('</idx:orth>')
        	
	return ''.join(out)

def kreiArtikon(s):
	"""
	Создание отдельной словарной статьи.
	"""

	contents = ['<p> ']
	isKursivo = False
	bazo = ""
	indekso = ""
		
	# Обрабатываем символы квадратных кавычек
	s = s.replace(u"<<", u"«")
	s = s.replace(u">>", u"»")
	
	for line in s.splitlines():
		#line = line.strip()
		
		# Удаляем строчку если она начинается с символов 200 или !!!
		if len(line) > 0 and line[0:2] in ('20', "!!"): line = ' '
		
		# Если в начале строки ключевое слово, то создаём индекс
		elif len(line) > 0 and line[0] == '[':
			# Выделяем словарное эсперанто-слово
			vorto = line[1:line.find(']')]
			# Определяем базовую часть слова для подстановки в слова с тильдой
			if vorto.find('|') > 0: bazo = vorto[:line.find('|')]
			elif vorto.find('~') < 0 and len(bazo) < 1: bazo = vorto
			
			indekso = kreiIndekso(vorto, bazo)
			contents.append(indekso)
			if (len(indekso)) < 2:
				print "Bazo: [%s], Vorto: [%s]" % (bazo, vorto)
		else: contents.append(' ')

		isStrike = False
		rusaVorto = []
		contents.append(' ')
		out_dict.append(u'\t')
		#out_dict.append(unicode(line))
		for c in line:
			if len(rusaVorto) > 0 and (c in '[]_/.,;{}<>='):
				contents.append(u'<idx:key name="Rusa" key="%s"/>' %
					 (''.join(rusaVorto)).strip())
				rusaVorto = []
			if c == "[": contents.append("<b>")
			elif c == ']': contents.append("</b>")
			elif c == '_':
				out_dict.append(u'_')
				isKursivo = not isKursivo
				if isKursivo:
					contents.append("<i>")
				else: contents.append("</i>")
			elif c == '{': contents.append("<small>")
			elif c == '}': contents.append("</small>")
			elif c == '/':
				contents.append(u'·')
				out_dict.append(u'·')
			# elif c == '|': contents.append(u'▪')
			elif c == '|': contents.append(u'</b>||<b>')
			elif c == '`': isStrike = True
			elif c == '<': out_dict.append(u'{')
			elif c == '>': out_dict.append(u'}')
			elif c == '\t': contents.append(' ')
			elif c == '@':
				contents.append(u'◊')
				out_dict.append(u'◊')
			else:
				contents.append(c)
				out_dict.append(unicode(c))
				# Если стоял символ ударения то добавляем специальный код
				if isStrike:
					contents.append(u"́")
					out_dict.append(u"́")
					isStrike = False
				if not isKursivo:
					if (c in RusaLetero) or (c == ' ' and len(rusaVorto) > 0):
						rusaVorto.append(c)
						
	# Закрываем определение последнего слова
	contents.append('</p>\n')
	
	s = ''.join(contents)

	if len(indekso) > 1:
		return '<idx:entry name="vortaro">%s</idx:entry>' % s
	else : return s

def kreiDosieron(nomo):     
	"""
	Создание на основе исходного текстового файла из каталога DIR_SOURCE
	файла в формате XHTML для Mobipocket Reader. Получаемый файл сохраняется
	в каталоге DIR_MOBI_XHTML
	"""
	
	global threeSymbolsDict

	print "Faras dosieron: ", nomo

	# Заголовок файла XHTML
	out = [u"""<html><head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<title>Esperanta-rusa vortaro</title></head><body>""", '']

	# Альтернативный индекс по первым трём буквам
	threeSymbolsDict = {}

	# Если файл с примечаниями (w.txt)
	isAbbr = nomo[0] == 'w'

	# Считываем исходный текстовый файл, разбивая на словарные статьи,
        # разделённые двойным переводом каретки.
	data = open(DIR_SOURCE + '%s.txt'%nomo,'r').read().decode('cp1251').split("\n\n")

	# Удаляем первую строчку если она начинается с символа доллара.
	if data[0][0] == '$': data[0:1] = []

	# Перебираем все словарные статьи создавая нужную разметку XTML
	for i in data:
                # Исключаем внутренние комментарии {{...}}
		s = re.sub("{{.*}}","",i)
		
		# Если файл с примечаниями (w.txt), то удаляем спец-разметку \head\ и \p\
		if isAbbr:
			s = re.sub("\\\\p\\\\","",s)	
			s = re.sub("\\\\/p\\\\","",s)
			s = re.sub("\\\\head\\\\","",s)
			s = re.sub("\\\\/head\\\\","",s)
		# Создаём словарну статью
		out.append(unicode(kreiArtikon(s)))

	# Добавляем окончание для файла XHTML
	out.append(u'</body></html>')
	
	if 1 == 2 : #not isAbbr:
		altIndex = []
		keys = threeSymbolsDict.keys()
		keys.sort()
		print keys
		for i in keys:
			altIndex.append('<A HREF="#%s">%s</A> ' % (threeSymbolsDict[i], i))
		altIndex.append('<HR>')
		out[1] = ''.join(altIndex)
		
    # Заменяем все эсперанто буквы в формате CX их аналогом в юникоде.
	xhtml = ''.join(out)
	for c in cx2eo:		xhtml = xhtml.replace(c, cx2eo[c])                
	
	# Обрабатываем русские сокращения
	for f in open(DIR_CONFIG + 'fako.cfg','r').readlines():
		x = f.decode('cp1251').split(" - ")
		xhtml = xhtml.replace("<i>" + x[0],
		u'<i><idx:key name="Fako" key="%s"/><span title="%s">%s</span>'
		 % (x[1], x[1], x[0]))
	
	# Записываем файл в формате xHTML
	open(DIR_MOBI_XHTML + '%s.html'%nomo,'w').write(xhtml.encode('utf8'))
	return None

def main():
	for fileName in os.listdir ( DIR_SOURCE ):
		if fileName[0] == '.' : continue
		if fileName[-4:] == '.txt' : kreiDosieron(fileName[:-4])
	dict_file = ''.join(out_dict)
	for c in cx2eo:		dict_file = dict_file.replace(c, cx2eo[c])
	# Записываем файл в формате DICT
	open(DIR_DICT + 'ervo-dict.txt','w').write(dict_file.encode('utf8'))
	unicode2palm(DIR_MOBI, DIR_PALM)
	unicode2palm(DIR_MOBI_XHTML, DIR_PALM_XHTML)
	return None
main()
